﻿/////////////////////////////////////////////////////////////////////////
//
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// This code is licensed under the terms of the Microsoft Kinect for
// Windows SDK (Beta) License Agreement:
// http://kinectforwindows.org/KinectSDK-ToU
//
/////////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Research.Kinect.Nui;
using Coding4Fun.Kinect.Wpf;
using Midi;

namespace SkeletalTracking
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    /// 

   

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        //Kinect Runtime
        Runtime nui; 

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            SetupKinect();
            MidiOutput.outputDevice = OutputDevice.InstalledDevices[0];
            //System.Console.WriteLine(MidiOutput.outputDevice);

        }

        private void SetupKinect()
        {
            if (Runtime.Kinects.Count == 0)
            {
                this.Title = "No Kinect connected"; 
            }
            else
            {
                
                //use first Kinect
                nui = Runtime.Kinects[0];

                //Initialize to do skeletal tracking
                nui.Initialize(RuntimeOptions.UseSkeletalTracking);
                //OutputDevice outputDevice = OutputDevice.InstalledDevices[0];
                
                //add event to receive skeleton data
                nui.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(nui_SkeletonFrameReady);
                

                //to experiment, toggle TransformSmooth between true & false
                // parameters used to smooth the skeleton data
                nui.SkeletonEngine.TransformSmooth = false;
                TransformSmoothParameters parameters = new TransformSmoothParameters();
                parameters.Smoothing = 0.7f;
                parameters.Correction = 0.3f;
                parameters.Prediction = 0.4f;
                parameters.JitterRadius = 1.0f;
                parameters.MaxDeviationRadius = 0.5f;
                nui.SkeletonEngine.SmoothParameters = parameters;

                

            }
        }

        void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            
            SkeletonFrame allSkeletons = e.SkeletonFrame;
            

            //get the first tracked skeleton
            SkeletonData skeleton = (from s in allSkeletons.Skeletons
                                     where s.TrackingState == SkeletonTrackingState.Tracked
                                     select s).FirstOrDefault();



            if (skeleton != null)
            {
                //set position
                SetEllipsePosition(HeadEllipse, skeleton.Joints[JointID.Head]);
                SetEllipsePosition(HandLeftEllipse, skeleton.Joints[JointID.HandLeft]);
                SetEllipsePosition(HandRightEllipse, skeleton.Joints[JointID.HandRight]);
                SetEllipsePosition(AnkleLeftEllipse, skeleton.Joints[JointID.AnkleLeft]);
                SetEllipsePosition(AnkleRightEllipse, skeleton.Joints[JointID.AnkleRight]);
                SetEllipsePosition(ElbowLeftEllipse, skeleton.Joints[JointID.ElbowLeft]);
                SetEllipsePosition(ElbowRightEllipse, skeleton.Joints[JointID.ElbowRight]);
                SetEllipsePosition(FootLeftEllipse, skeleton.Joints[JointID.FootLeft]);
                SetEllipsePosition(FootRightEllipse, skeleton.Joints[JointID.FootRight]);
                SetEllipsePosition(HipCenterEllipse, skeleton.Joints[JointID.HipCenter]);
                SetEllipsePosition(HipLeftEllipse, skeleton.Joints[JointID.HipLeft]);
                SetEllipsePosition(HipRightEllipse, skeleton.Joints[JointID.HipRight]);
                SetEllipsePosition(KneeLeftEllipse, skeleton.Joints[JointID.KneeLeft]);
                SetEllipsePosition(KneeRightEllipse, skeleton.Joints[JointID.KneeRight]);
                SetEllipsePosition(ShoulderCenterEllipse, skeleton.Joints[JointID.ShoulderCenter]);
                SetEllipsePosition(ShoulderLeftEllipse, skeleton.Joints[JointID.ShoulderLeft]);
                SetEllipsePosition(ShoulderRightEllipse, skeleton.Joints[JointID.ShoulderRight]);
                SetEllipsePosition(SpineEllipse, skeleton.Joints[JointID.Spine]);
                SetEllipsePosition(WristLeftEllipse, skeleton.Joints[JointID.WristLeft]);
                SetEllipsePosition(WristRightEllipse, skeleton.Joints[JointID.WristRight]);



                var depth = GetRelativeZ(skeleton.Joints[JointID.HandLeft], skeleton.Joints[JointID.ShoulderCenter]);

                int depthState = GlobalVar.GlobalValue;

                if (depth > 0.37)
                {
                    if (depthState == 0)
                    {
                        PlayNote(skeleton.Joints[JointID.HandLeft], skeleton.Joints[JointID.HandRight]);
                        System.Console.WriteLine(depth);
                        GlobalVar.GlobalValue = 1;
                    }
                }

                if (depth <= 0.36)
                {
                    if (depthState == 1)
                    {
                        GlobalVar.GlobalValue = 0;
                    }
                }
            }
        }

        private void SetEllipsePosition(FrameworkElement ellipse, Joint joint)
        {
            var scaledJoint = joint.ScaleTo(640, 480, .5f, .5f);

            Canvas.SetLeft(ellipse, scaledJoint.Position.X);
            Canvas.SetTop(ellipse, scaledJoint.Position.Y);
            //System.Console.WriteLine(scaledJoint.Position.X);
            
        }

        private float GetRelativeZ(Joint joint, Joint baseJoint)
        {

            var scaledJoint = joint.ScaleTo(640, 480, .5f, .5f);
            var scaledBaseJoint = baseJoint.ScaleTo(640, 480, .5f, .5f);

            float relX = (scaledBaseJoint.Position.Z - scaledJoint.Position.Z);

            //System.Console.WriteLine("relative position:");
            //System.Console.WriteLine(relX);

            return relX;

        }

        private void PlayNote(Joint leftJoint, Joint rightJoint)
        {
            var scaledLeftJoint = leftJoint.ScaleTo(640, 480, .5f, .5f);
            var scaledRightJoint = rightJoint.ScaleTo(640, 480, .5f, .5f);
            float leftY = scaledLeftJoint.Position.Y;
            float rightY = scaledRightJoint.Position.Y;

            

            
            MidiOutput.playNote(leftY, rightY);

            

        }

        private void Window_Closed(object sender, EventArgs e)
        {
            //Cleanup
            nui.Uninitialize();
        }
    }
}
